package demographic.identity
import com.vividsolutions.jts.geom.*
import grails.converters.JSON

//
import org.basex.core.*;
import org.basex.core.cmd.*;
import org.basex.query.*;
import org.basex.query.iter.*;
import org.basex.query.value.item.*;

import javax.ws.rs.core.MediaType;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.WebResource
import groovy.sql.Sql;
///

class LugarController {

    static allowedMethods = [save: "POST", update: "POST", delete: "POST"]

    static Context context = new Context();


    def index = {
        redirect(action: "list", params: params)
    }

    def filtrar = {
        params.max = Math.min(params.max ? params.int('max') : 20, 100)
        params.offset = params.offset ? params.offset.toInteger() : 0
        def selectValue = null
        def existLugar = null
        if (params.filterTipoLugarValue!=null){
            selectValue = params.filterTipoLugarValue
            session["selectedValue"] = params.filterTipoLugarValue;
        }else{
            selectValue = session["selectedValue"]
        }
        if (params.filterNombreValue=="" || params.filterNombreValue==null){
            existLugar =  Lugar.createCriteria().list(max:params.max, offset:params.offset){
                    eq("tipolugar", selectValue)
            }
        }else{
            existLugar =  Lugar.createCriteria().list(max:params.max, offset:params.offset){
                and{
                    like("nombre", params.filterNombreValue)
                    eq("tipolugar", selectValue)
                }
            }
        }
        [lugarInstanceList: existLugar, lugarInstanceTotal: existLugar.getTotalCount(), selectValue:selectValue]
    }

    def list = {
        def selectedValue = session["selectedValue"]
        params.max = Math.min(params.max ? params.int('max') : 20, 100)
        [lugarInstanceList: Lugar.list(params), lugarInstanceTotal: Lugar.count()]
    }

    def create = {
        def entidades = Lugar.findAllByTipolugar("Estado")
        def lugarInstance = new Lugar()
        lugarInstance.properties = params
        return [lugarInstance: lugarInstance, entidades:entidades]
    }

    def save = {
        def point = null
        def place = Lugar.findAllByNombre(params.nombre)
        if (place.size() > 0 ) {
            flash.message = "${message(code: 'lugar.error.duplicado', args: [message(code: 'lugar.label', default: 'Lugar')])}"
            redirect(action: "create")
        }
        if (params.latitud!="" && params.longitud!=""){
            def latitud = params.latitud.toDouble()
            def longitud = params.longitud.toDouble()
            def coordinate = new Coordinate(latitud,longitud)
            def precisionModel = new PrecisionModel();
            point = new Point(coordinate,precisionModel,4326)
        }
        def lugarInstance = new Lugar(params)
        lugarInstance.setCoordenadas(point)
        if (lugarInstance.save(flush: true)) {
            flash.message = "${message(code: 'default.created.message', args: [message(code: 'lugar.label', default: 'Lugar'), lugarInstance.id])}"
            redirect(action: "show", id: lugarInstance.id)
        }
        else {
            render(view: "create", model: [lugarInstance: lugarInstance])
        }
    }

    def show = {
        def lugarInstance = Lugar.get(params.id)
        if (!lugarInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
            redirect(action: "list")
        }
        else {
            [lugarInstance: lugarInstance]
        }
    }

    def edit = {
        def lugarInstance = Lugar.get(params.id)
        if (!lugarInstance) {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
            redirect(action: "list")
        }
        else {
            if (lugarInstance.coordenadas!=null){
                def latitud = lugarInstance.coordenadas.getX()
                def longitud = lugarInstance.coordenadas.getY()
                return [lugarInstance: lugarInstance, latitud:latitud, longitud:longitud]
            }
            return [lugarInstance: lugarInstance]
        }
    }

    def update = {
        def point = null
        if (params.latitud!="" && params.longitud!=""){
            def latitud = params.latitud.toDouble()
            def longitud = params.longitud.toDouble()
            def coordinate = new Coordinate(latitud,longitud)
            def precisionModel = new PrecisionModel();
            point = new Point(coordinate,precisionModel,4326)

        }
        def lugarInstance = Lugar.get(params.id)
        if (lugarInstance) {
            if (params.version) {
                def version = params.version.toLong()
                if (lugarInstance.version > version) {
                    
                    lugarInstance.errors.rejectValue("version", "default.optimistic.locking.failure", [message(code: 'lugar.label', default: 'Lugar')] as Object[], "Another user has updated this Lugar while you were editing")
                    render(view: "edit", model: [lugarInstance: lugarInstance])
                    return
                }
            }
            params.coordenadas = point;
            lugarInstance.properties = params
            if (!lugarInstance.hasErrors() && lugarInstance.save(flush: true)) {
                flash.message = "${message(code: 'default.updated.message', args: [message(code: 'lugar.label', default: 'Lugar'), lugarInstance.id])}"
                redirect(action: "show", id: lugarInstance.id)
            }
            else {
                render(view: "edit", model: [lugarInstance: lugarInstance])
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
            redirect(action: "list")
        }
    }

    def delete = {
        def lugarInstance = Lugar.get(params.id)
        if (lugarInstance) {
            try {
                lugarInstance.delete(flush: true)
                flash.message = "${message(code: 'default.deleted.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
                redirect(action: "list")
            }
            catch (org.springframework.dao.DataIntegrityViolationException e) {
                flash.message = "${message(code: 'default.not.deleted.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
                redirect(action: "show", id: params.id)
            }
        }
        else {
            flash.message = "${message(code: 'default.not.found.message', args: [message(code: 'lugar.label', default: 'Lugar'), params.id])}"
            redirect(action: "list")
        }
    }

    def showCombo = {
        def array
        array = params.id.split	("!")
        def id =  array[0] as Long;
        def option = array[1] as Long;
            if(id == 0){
                def list = Lugar.createCriteria().list{
                    eq('tipolugar',"Pais")
                }
                render """<select name="padre.id" class="selectci" id="padre.id"> <option value="-1">Seleccione</option>""" + list.collect {"""<option value="${it.id}">${it.nombre} </option>"""} + """</select>"""
            }
            if(id >= 1){
                def list = Lugar.createCriteria().list{
                    padre{
                        eq('id',id)
                    }
                }
                switch (option) {
                    case 1:
                        render """<select name="padre.id" id="padre.id" class="selectci"><option value=null>Nuevo Pais</option> </select>"""
                    break
                    case 2:
                        render """<select name="padre.id" id="padre.id" class="selectci"> <option value="-1">Seleccione</option>""" + list.collect {"""<option value="${it.id}">${it.nombre} </option>"""} + """</select>"""
                    break
                    case 3:
                        render """<select name="entidad_combo" class="selectci" id="entidad_combo" ><option value="-1">Seleccione</option>""" + list.collect {"""<option value="${it.id}">${it.nombre} </option>"""} + """</select>"""
                    break
                    case 4:
                        render """<select name="municipio_combo" class="selectci" id="entidad_combo" ><option value="-1">Seleccione</option>""" + list.collect {"""<option value="${it.id}">${it.nombre} </option>"""} + """</select>"""
                    break
                }
            }
    }

    def changeLabel = {
        render """<label for="padreLabel" id="padreLabel" name="padreLabel">${params.message}</label>"""
    }

    def editarMapa = {
        def estados = Lugar.findAllByTipolugarLike("Estado")
        [estados:estados]
    }

    def irIdMapa  = {
       def latlong = Lugar.findById(params.direccion)
        if (latlong == null || latlong.coordenadas==null ){
            flash.message = "Error: La Parroquia seleccionada no posee coordenadas. Agregarlas en el modulo de 'Datos Demograficos'"
            redirect(action:'editarMapa')
        }
        session["latlong"] = latlong;
        redirect(url: grailsApplication.config.ruta.idEditor.url+latlong.coordenadas.getY()+"/"+latlong.coordenadas.getX())
    }

    def lugarFinder = {
        def LugarFound = Lugar.withCriteria{
            ilike 'nombre', params.term + '%'
        }
        render (LugarFound.nombre as JSON)
    }




    def ventanaId = {
        println("entro en id!")
        Client client = Client.create();

        //////////////aqui puede ser tele bla bla el usuario que queramos
        String left = null;// ="-66.920192";
        String bottom = null;// ="10.503636";
        String right = null;// ="-66.917269";
        String top = null;// = "10.505667";
        String msg = null;

        WebResource resource = client
                .resource(grailsApplication.config.ruta.openStreet.api.changeSets
                + grailsApplication.config.ruta.openStreet.user);
        msg = resource.path("").accept(MediaType.TEXT_PLAIN).get(String.class);
        Document parse;
        println("entro en id!" +msg)
        try {
            DocumentBuilder newDocumentBuilder = DocumentBuilderFactory
                    .newInstance().newDocumentBuilder();
            parse = newDocumentBuilder.parse(new ByteArrayInputStream(msg
                    .getBytes()));
            Node nodo;
            nodo = parse.getFirstChild();
            NodeList lista = nodo.getChildNodes();
            nodo = lista.item(1);
            NamedNodeMap attr = nodo.getAttributes();
            nodo = attr.getNamedItem("min_lat");
            bottom = nodo.getNodeValue();
            nodo = attr.getNamedItem("max_lat");
            top = nodo.getNodeValue();
            nodo = attr.getNamedItem("min_lon");
            left = nodo.getNodeValue();
            nodo = attr.getNamedItem("max_lon");
            right = nodo.getNodeValue();

        } catch (SAXException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        WebResource resource1 = client.resource(grailsApplication.config.ruta.openStreet.api.mapBox+left+","+bottom+","+right+","+top);
        msg = resource1.path("").accept(MediaType.TEXT_XML).get(String.class);

        BufferedReader br = null;
        new CreateDB("DBExample",msg).execute(context);

        new Open("DBExample").execute(context);
        new CreateIndex("fulltext").execute(context);
        br = new BufferedReader(new FileReader(grailsApplication.config.ruta.xquery));
        StringBuilder sb = new StringBuilder();
        String line;
        line = br.readLine();
        while (line != null) {
            sb.append(line);
            sb.append((char) 32);
            line = br.readLine();
        }
        br.close();


        String query = sb.toString();


        try {
            iterate(query);
        } catch (QueryException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }

        context.close();


    }

     void iterate(String query) throws QueryException {
        def latlong  = session["latlong"]
        QueryProcessor proc = new QueryProcessor(query, context);
        Sql sql = Sql.newInstance(grailsApplication.config.ruta.sql.pool,
                grailsApplication.config.ruta.sql.user,
                grailsApplication.config.ruta.sql.user,
                grailsApplication.config.ruta.sql.driver)
        Iter iter = proc.iter();
        for(Item item; (item = iter.next()) != null;) {
         //   System.out.println(item.toJava().toString().replaceAll("####",latlong.getId().toString()));
            sql.execute(item.toJava().toString().replaceAll("####",latlong.getId().toString()))
       //     System.out.println("aja");
        }
        proc.close();
    }


}
